package ai;

import game.Game;

public class Minmax extends Ai {

	//Ai playingfield copy
	protected byte[][] aiPlayingField;
	
	//To keep track of the calculations
	protected int counter;
	
	//Constructor
	public Minmax(Game game, byte side)
	{
		super(game, side);
		this.aiPlayingField = new byte[Game.XSIZE][Game.YSIZE];
	}
	
	protected int getZet()
	{
		//Copy a new playing field to the ai-array.
		copyPlayingField( this.game.getPlayingField() );
		
		//Set the counter to zero
		this.counter = 0;
		
		//Call the chooseMove function which tries to select an optiomal move
		Reply reply = chooseMove( this.side, 6 );
		
		
		return reply.bestmove;
	}
	
	//Recursive function to determine the optimal move
	private Reply chooseMove(byte side, int amount)
	{
		byte opponent;
		int value;
		int bestmove = 0;
		Reply reply;
		
		//Increment the counter
		this.counter++;
		
		//Base case
		if (this.game.checkFourOnRow(this.aiPlayingField) != Game.UNCLEAR || amount < 1)
		{
			return new Reply(this.game.checkFourOnRow(this.aiPlayingField));
		}
		
		//Assign values depending on which side we are currently on
		if (side == Game.PLAYER1)
		{
			opponent = Game.PLAYER2;
			value = Game.PLAYER2_WIN;
		}
		else
		{
			opponent = Game.PLAYER1;
			value = Game.PLAYER1_WIN;
		}
		
		
		//Select a default move (the first not full column from the left)
		for (int i = 0; i < Game.XSIZE; i++)
		{
			if ( ! this.columnIsFull(i) )
			{
				bestmove = i;
				break;
			}
		}
		
		
		//Main loop (for each column)
		for (int i = 0; i < Game.XSIZE; i++)
		{
			if ( ! this.columnIsFull(i) )
			{
				//Insert a token in the current column
				placeToken(i, side);
				
				//Call yourself recursively
				reply = chooseMove(opponent, amount-1);
				
				//Remove the token again
				removeToken(i);
				
				
				//Update the return values if we've found a better move
				if (side == Game.PLAYER1 && reply.value < value ||
						side == Game.PLAYER2 && reply.value > value)
				{
					value = reply.value;
					bestmove = i;
				}
				
			}
		}
		
		return new Reply(value, bestmove);
	}
	

	//Place a token in a column
	protected void placeToken(int column, byte side)
	{
		//For each row
		for (int j = Game.YSIZE - 1; j >= 0; j--)
		{
			if (this.aiPlayingField[column][j] == Game.EMPTY)
			{
				this.aiPlayingField[column][j] = side;
				return;
			}
		}
	}
	
	//Remove a token from a column
	protected void removeToken(int column)
	{
		//For each row
		for (int j = 0; j < Game.YSIZE; j++)
		{
			if (this.aiPlayingField[column][j] != Game.EMPTY)
			{
				this.aiPlayingField[column][j] = Game.EMPTY;
				return;
			}
		}
	}
	

	//Copy the playingfield array
	protected void copyPlayingField(byte[][] source)
	{
		//For each column
		for (int x = 0; x < Game.XSIZE; x++)
		{
			//For each row
			for (int y = 0; y < Game.YSIZE; y++)
			{
				this.aiPlayingField[x][y] = source[x][y];
			}
		}
	}


	//A function that checks if a column is full
	protected boolean columnIsFull(int column)
	{
		return (this.aiPlayingField[column][0] != Game.EMPTY);
	}
	
}
